%{
#include <stdio.h>
extern FILE *yyin;
%}

%token ID	
%token CLASS
%token INT_LITERAL
%token FLOAT_LITERAL
%token IF
%token ELSE
%token BREAK
%token CONTINUE
%token FLOAT
%token FOR
%token INT
%token RETURN
%token VOID
%token WHILE
%token EXTERNINVK
%token MENORIGUAL
%token MAYORIGUAL
%token IGUALDAD
%token DISTINTO
%token YLOGICO
%token OLOGICO
%token INCREMENTO
%token DECREMENTO
%token BOOL
%token STRING_LITERAL
%token TRUE
%token FALSE
%nonassoc VACIO

%start program

%%
program: CLASS ID body
       ;

body:'{''}' 
    | '{'decymet'}'
    ;

decymet: field_decls  
       | method_decls 
       | field_decls method_decls 
       ;

field_decls: field_decl 
           | field_decls field_decl
           ;
		
field_decl: type names ';'
          ;
   
names: id
     | names ',' id
     ;
     
          
id: ID
  | ID '['INT_LITERAL']'
  ;



method_decls: method_decl
            | method_decls method_decl
            ;
            
method_decl: type ID atributos block 
           | VOID ID atributos block
           ;

params: param
      | params ',' param
      ;

param: type ID
     ;

atributos: '('')'
         | '('params')'
         ;
		
block:'{''}'
     |'{'field_decls'}'
     |'{' statements '}'
     |'{' field_decls statements '}'
     ;

statements: statement
         | statements statement
         ;

statement: location assign_op expr ';'
         |method_call ';'
         |conditional
         |FOR asig ',' expr block
         |WHILE expr block
         |RETURN expr ';'
         |BREAK ';'
         |CONTINUE ';'
         |';'
         |block 
         |RETURN ';'
         ;
         
asig: ID '=' expr 
    ;

conditional: IF '(' expr ')' block else 
         ;

else: %prec VACIO
    | ELSE block 
    ;

assign_op: '='
         | INCREMENTO
         | DECREMENTO
         ;


expr: conjuncion
    | expr OLOGICO conjuncion
    ;

conjuncion: comp
          | conjuncion YLOGICO comp
          ;
          
comp: relacc
      |comp IGUALDAD relacc
      |comp DISTINTO relacc
      ;
      
relacc: arit
      | relacc '<' arit
      | relacc '>' arit
      | relacc MAYORIGUAL arit
      | relacc MENORIGUAL arit
      ;
      
arit: mod
    | arit '+' mod
    | arit '-' mod
    ;
    
mod: log
   | mod '*' log
   | mod '/' log
   | mod '%' log
   ;
   
log: literales
   | '!' log
   | '-' log
   ;
   
   

literales: method_call
         |'(' expr ')'
         | INT_LITERAL
         | FLOAT_LITERAL
         | bool_literal
         | ID
         | ID '[' expr ']' 
         ;		

bool_literal: TRUE
            | FALSE
            ;

location: ID
        | ID '['expr']'
        ;
exprs2: expr
      | exprs2 ',' expr
      ;
      
method_call: ID '(' ')'
           | ID '('exprs2')' 
           | EXTERNINVK '('STRING_LITERAL ',' type2 ','  extern ')'
           | EXTERNINVK '('STRING_LITERAL ',' type2  ')'
           ;

type2: type
     | VOID
     ;
     

type: INT
    | FLOAT
    | BOOL
    ;

extern: externinvk_arg
      | extern ',' externinvk_arg
      ;

externinvk_arg: expr
              | STRING_LITERAL
              ;

%%

int yywrap(){return 1;}

int main(int argc, char  *argv[])
{
 
    printf("%s\n", argv[1]);
    yyin = fopen(argv[1], "r");
    if (yyparse()==0){printf("El programa no posee errores sintacticos\n");}
   
  
  return 0;
}	
	
